package com.hrw.android.player.media;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.media.MediaPlayer;

public class PlayerEngineImpl implements IPlayerEngine {

	public PlayerEngineImpl() {
		if (null == mediaPlayerEngine) {
			mediaPlayerEngine = new MediaPlayerEngine();

		}
	}

	public enum PlaybackMode {
		NORMAL, SHUFFLE, REPEAT, SHUFFLE_AND_REPEAT
	}

	private PlaybackMode playbackMode = PlaybackMode.NORMAL;

	private List<Integer> playbackOrder = new ArrayList<Integer>();

	private String path;

	private int selectedOrderIndex = -1;

	private List<String> mediaList = null;

	private MediaPlayerEngine mediaPlayerEngine = null;

	public int getSelectedIndex() {
		return playbackOrder.get(selectedOrderIndex);
	}

	public int getSelectedOrderIndex() {
		return selectedOrderIndex;
	}

	@Override
	public void setSelectedOrderIndex(int selected) {
		this.selectedOrderIndex = selected;
		path = mediaList.get(getSelectedIndex());
	}

	private boolean isEmpty() {
		return mediaList.size() == 0;
	}

	private int getListSize() {
		return mediaList.size();
	}

	public PlaybackMode getPlaybackMode() {
		return playbackMode;
	}

	public void setPlaybackMode(PlaybackMode playbackMode) {
		this.playbackMode = playbackMode;
	}

	@Override
	public void forward(int time) {
		mediaPlayerEngine.seekTo(time);

	}

	@Override
	public boolean isPlaying() {
		return mediaPlayerEngine.isPlaying();
	}

	@Override
	public void previous() {
		if (!isEmpty()) {
			selectedOrderIndex--;
			if (selectedOrderIndex < 0) {
				selectedOrderIndex = mediaList.size() - 1;
			}
			this.path = mediaList.get(getSelectedIndex());
		}

	}

	@Override
	public void next() {
		if (!isEmpty()) {
			// selected begins from zero.
			selectedOrderIndex++;
			selectedOrderIndex %= mediaList.size();
			this.path = mediaList.get(playbackOrder.get(selectedOrderIndex));
			play();
		}

	}

	@Override
	public void pause() {
		mediaPlayerEngine.pause();

	}

	@Override
	public void play() {
		mediaPlayerEngine.play(path);
	}

	@Override
	public void reset() {
		mediaPlayerEngine.reset();

	}

	@Override
	public void rewind(int time) {
		mediaPlayerEngine.seekTo(time);

	}

	@Override
	public void skipTo(int index) {
		setSelectedOrderIndex(index);

	}

	@Override
	public void stop() {
		mediaPlayerEngine.stop();
		play();
	}

	private class MediaPlayerEngine extends MediaPlayer {

		private boolean isPause = false;

		public boolean isPause() {
			return isPause;
		}

		public void setPause(boolean isPause) {
			this.isPause = isPause;
		}

		@Override
		public void reset() {
			isPause = false;
			super.reset();
		}

		public void play(String path) {
			try {
				this.setDataSource(path);
				if (!isPause) {
					super.prepare();
				}
				super.start();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

		@Override
		public void stop() throws IllegalStateException {
			isPause = false;
			super.stop();
		}

		@Override
		public void pause() throws IllegalStateException {
			isPause = true;
			super.pause();
		}

		public void previousOrNext(String path) throws IllegalStateException,
				IOException {
			isPause = false;
			play(path);

		}
	}

	@Override
	public String getPlayingPath() {
		return this.path;
	}

	@Override
	public void setPlayingPath(String path) {
		this.path = path;

	}

	@Override
	public void setMediaPathList(List<String> pathList) {
		this.mediaList = pathList;
		calculateOrder(true);

	}

	private void calculateOrder(boolean force) {
		int beforeSelected = 0;
		if (!playbackOrder.isEmpty()) {
			beforeSelected = playbackOrder.get(selectedOrderIndex);
			playbackOrder.clear();
		}

		for (int i = 0; i < getListSize(); i++) {
			playbackOrder.add(i, i);
		}

		if (null == playbackMode) {
			playbackMode = PlaybackMode.NORMAL;
		}
		switch (playbackMode) {
		case NORMAL: {
			break;
		}
		case SHUFFLE: {
			Collections.shuffle(playbackOrder);
			break;
		}
		case REPEAT: {
			selectedOrderIndex = beforeSelected;
			break;
		}
		case SHUFFLE_AND_REPEAT: {
			break;
		}
		default: {
			break;
		}
		}

	}

}
